﻿#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkSmartPointer.h>
#include <vtkCamera.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkNamedColors.h>
#include <vtkClipPolyData.h>
#include <vtkProperty.h>
#include <vtkPlane.h>
#include <vtkSTLReader.h>
#include <vtkPlaneCollection.h>
#include <vtkClipClosedSurface.h>
#include <vtkWorldPointPicker.h>

/// 通过plane切一个面出来，并显示剩下的部分
///


static vtkSmartPointer<vtkRenderer> sRender;
/**************************************************************************************************/
class PointPickerInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
    static PointPickerInteractorStyle* New();
    vtkTypeMacro(PointPickerInteractorStyle, vtkInteractorStyleTrackballCamera);

    virtual void OnLeftButtonDown()
    {
        //打印鼠标左键像素位置
        std::cout << "Picking pixel: " << this->Interactor->GetEventPosition()[0]
            << " " << this->Interactor->GetEventPosition()[1] << std::endl;
        //注册拾取点函数
        this->Interactor->GetPicker()->Pick(
            this->Interactor->GetEventPosition()[0],
            this->Interactor->GetEventPosition()[1],
            0,  // always zero.
            sRender
//            this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()
            );
        //打印拾取点空间位置
        double picked[3];
        this->Interactor->GetPicker()->GetPickPosition(picked);
        std::cout << "Picked value: " << picked[0] << " " << picked[1] << " " << picked[2] << std::endl;
        //对拾取点进行标记
        vtkSmartPointer<vtkSphereSource> sphereSource =
            vtkSmartPointer<vtkSphereSource>::New();
        sphereSource->Update();

        vtkSmartPointer<vtkPolyDataMapper> mapper =
            vtkSmartPointer<vtkPolyDataMapper>::New();
        mapper->SetInputConnection(sphereSource->GetOutputPort());

        vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
        actor->SetMapper(mapper);
        actor->SetPosition(picked);
        actor->SetScale(1);
        actor->GetProperty()->SetColor(0.0, 1.0, 0.0);
        sRender->AddActor(actor);
//        this->Interactor->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->AddActor(actor);

        vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
    }
};
/**************************************************************************************************/

vtkStandardNewMacro(PointPickerInteractorStyle);


int main(int, char *[])
{
    std::string inputFilename = "D:/VTK/demo_pig.stl";

    vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
    reader->SetFileName(inputFilename.c_str());
    reader->Update();

    vtkPlane *vPlane = vtkPlane::New();
    vtkSmartPointer<vtkPlane> plane =
        vtkSmartPointer<vtkPlane>::New();
    plane->SetOrigin(10, 10, -10);
    plane->SetNormal(0, 0, -1);

    // Need a plane collection for clipping
    vtkSmartPointer<vtkPlaneCollection>  planeCollection =
            vtkSmartPointer<vtkPlaneCollection>::New();
    planeCollection->AddItem(plane);

    // The clipper gennerates a clipped polygonial model
    vtkSmartPointer<vtkClipClosedSurface> clipper =
            vtkSmartPointer<vtkClipClosedSurface>::New();
    clipper->SetInputConnection(reader->GetOutputPort());
    clipper->SetClippingPlanes(planeCollection);
    clipper->SetGenerateFaces(1);
    clipper->SetScalarModeToLabels();
    clipper->Update();

//    vtkSmartPointer<vtkClipPolyData> clipPolyData =
//        vtkSmartPointer<vtkClipPolyData>::New();
//    clipPolyData->SetInputConnection(reader->GetOutputPort());
//    clipPolyData->SetClipFunction(plane);
//    clipPolyData->GenerateClippedOutputOn();
//    clipPolyData->Update();

    vtkSmartPointer<vtkPolyDataMapper> mapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(reader->GetOutputPort());

    vtkSmartPointer<vtkActor> actor =
        vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);

    vtkSmartPointer<vtkPolyDataMapper> outMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
    outMapper->SetInputConnection(clipper->GetOutputPort());

    vtkSmartPointer<vtkActor> outActor =
        vtkSmartPointer<vtkActor>::New();
    outActor->SetMapper(outMapper);

    vtkSmartPointer<vtkNamedColors> colors =
        vtkSmartPointer<vtkNamedColors>::New();

    vtkSmartPointer<vtkRenderer> renderer =
        vtkSmartPointer<vtkRenderer>::New();
    renderer->SetBackground(colors->GetColor3d("Slate_grey").GetData());
    renderer->AddActor(actor);
    renderer->SetViewport(0, 0, 0.5, 1);

    vtkSmartPointer<vtkRenderer> outRenderer =
        vtkSmartPointer<vtkRenderer>::New();
    outRenderer->SetBackground(colors->GetColor3d("Slate_blue").GetData());
    outRenderer->AddActor(outActor);
    outRenderer->SetViewport(0.5, 0, 1, 1);

    vtkSmartPointer<vtkRenderWindow> renderWindow =
        vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->SetSize(600, 300);
    renderWindow->AddRenderer(renderer);
    renderWindow->AddRenderer(outRenderer);

    // picker
//    vtkSmartPointer<vtkPointPicker> pointPicker =
//        vtkSmartPointer<vtkPointPicker>::New();
    vtkSmartPointer<vtkWorldPointPicker> pointPicker =
        vtkSmartPointer<vtkWorldPointPicker>::New();

    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetPicker(pointPicker);
    renderWindowInteractor->SetRenderWindow(renderWindow);

//    vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =
//        vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
    sRender = outRenderer;  // interactive
    vtkSmartPointer<PointPickerInteractorStyle> style =
        vtkSmartPointer<PointPickerInteractorStyle>::New();
    renderWindowInteractor->SetInteractorStyle(style);

    renderWindow->Render();
    renderWindowInteractor->Initialize();
    renderWindowInteractor->Start();

    return EXIT_SUCCESS;
}
